import { toCurrency } from "utils/formatPrice";

export interface IProduct {
  id: number;
  sku: number;
  title: string;
  description: string;
  availableSizes: string[];
  style: string;
  price: number;
  installments: number;
  currencyId: string;
  currencyFormat: string;
  isFreeShipping: boolean;
}

/**商品的筛选信息*/
export interface IProductFilter {
  /**空或空数组皆为不筛选*/
  sizes?: string[];
  /**排序字段名,放空不排序*/
  sortProp?: string;
  /**排序方法,放空不排序*/
  sort?: ESort;
}


/**商品当前选择的参数*/
export interface ICartProductSelectedOptions {
  selectedSize: string;
}

/**商品信息包含当前选择参数*/
export interface IProductWithSelected extends IProduct {
  selectedOptions: ICartProductSelectedOptions;
}

/**同商品的同选择为同一条, 由key字段标识唯一*/
export interface ICartProduct extends IProductWithSelected {
  /**由 buildCartProductKey() 方法生成*/
  key: string;
  quantity: number;
}

export interface IGetProductsResponse {
  products: IProduct[];
}





export enum ESort {
  Asc = 'Asc',
  Desc = 'Desc',
}

type IResultError={
  /**整个结果是否成功的,即data可用*/
  success: false;
  /**不成功则错误消息*/
  error: string;
  /**有的应用需要区分错误码*/
  code: number;
};
/**
 * 通用结果对象
 * @template T 
 */
export type IResult<T> = {
  /**整个结果是否成功的,即data可用*/
  success: true;
  /**数据*/
  data: T;
} | IResultError;

export class Result {
  public static success<T>(data: T): IResult<T> {
    return {
      success: true,
      data,
    };
  }
  public static error(code:number, error:string): IResultError {
    return {
      success: false,
      code,
      error,
    };
  }
}

export interface IReqCancel {
  cancel(): void;
}

/**异步请求结果*/
export interface IReqResult<T> {
  task: Promise<IResult<T>>;
  cancelToken: IReqCancel;
}



/**商品尺码筛选*/
export function productSizesFilter(product: IProduct, filter?: IProductFilter) {
  if (filter?.sizes && filter.sizes.length > 0) return product.availableSizes.filter(s => filter.sizes!.includes(s));
  return product.availableSizes;
}

/**
 * 本地筛选产品,一般正式环境不会使用,只在模拟数据时用到
 * @param product 
 * @param filter 
 * @returns true if filter 
 */
export function productFilter(product: IProduct, filter: IProductFilter): boolean {
  if (productSizesFilter(product, filter).length <= 0) return false;
  return true;
}
/**
 * 比较两个筛选条件是否一直
 * @param filter1 
 * @param filter2 
 * @returns true if product filter 
 */
export function eqProductFilter(filter1: IProductFilter, filter2: IProductFilter): boolean {
  //尺码简单不排序的直接比较好了,暂时顺序都是固定的
  if (filter1.sizes?.join(',') !== filter2.sizes?.join(',')) return false;
  return true;
}

/**构造商品的默认选择参数*/
export function buildDefProductSelectedOpt(product: IProduct, filter?: IProductFilter): ICartProductSelectedOptions {
  let pSizes = productSizesFilter(product, filter);
  const defSelectedSize = pSizes[0];
  return {
    selectedSize: defSelectedSize,
  };
}
/**
 * Builds product with def selected
 * @param product 
 * @param [sizesFilter] 如果有过滤尺码
 * @returns product with def selected 
 */
export function buildProductWithDefSelected(product: IProduct, filter?: IProductFilter): IProductWithSelected {
  const p = Object.assign({}, product) as IProductWithSelected;
  p.selectedOptions = buildDefProductSelectedOpt(product, filter);
  return p;
}

export function buildCartProductSelectedKey(opt: ICartProductSelectedOptions): string {
  return `s:${opt.selectedSize}`;
}
/**
 * Builds cart product key
 * @param product 
 * @param selectedOpt 
 * @returns cart product key 
 */
export function buildCartProductKey(product: IProductWithSelected): string {
  return `${product.id}_${buildCartProductSelectedKey(product.selectedOptions)}`;
}

export interface ICartTotal {
  /**最终合计价格*/
  totalPrice: number;
  /**总价格可以进行多少分期(最小的分期数),没有则为0*/
  minInstallments: number;
  /**商品总数量*/
  count: number;
}
/**
 * 统计购物车商品列表价格
 * @param cartProducts 
 * @param toCurrencyId 使用什么货币id统计
 * @returns cart product
 */
export function totalCartProduct(cartProducts: ICartProduct[], toCurrencyId: string): ICartTotal {
  let totalPrice = 0;
  let minInstallments = 0;
  let count = 0;

  //列表按商品id重新合并以及分组(忽略不同商品尺码等差别)
  cartProducts.forEach(p => {
    totalPrice += toCurrency(p.price, p.currencyId, toCurrencyId) * p.quantity;
    count += p.quantity;
    if (p.installments) {
      if (!minInstallments || p.installments < minInstallments) {
        minInstallments = p.installments
      }
    }
  });

  return {
    totalPrice,
    minInstallments,
    count,
  };
}